home *** CD-ROM | disk | FTP | other *** search
- //=================================================================================================
- // Build.CPP
- //-------------------------------------------------------------------------------------------------
- //
- // Copyright (c) 1994 by Todd A. Prater
- // All rights reserved.
- //
- //=================================================================================================
-
-
- #include <stdlib.h>
- #include <fstream.h>
- #include "Config.H"
- #include "Vector.H"
- #include "TrueType.H"
- #include "Geometry.H"
- #include "Build.H"
-
- #define IGNORE 2
- #define INSIDE 1
- #define OUTSIDE 0
-
-
-
- // ******************************************************
- // NOTE: Please excuse the debugging code
- // ******************************************************
-
-
-
- //===========================================================================================================
- // PolygonizeContour
- //-----------------------------------------------------------------------------------------------------------
- //===========================================================================================================
-
- void PolygonizeContour(TTFont& font,
- USHORT glyphnum,
- USHORT contournum,
- USHORT resolution,
- DOUBLE depth,
- POLYGON& polygon )
- {
-
- ULONG i,j;
- ULONG polyi;
- ULONG offcount,pointcount;
- ULONG consecutiveoffcount;
- INT lastwasoff;
- INT cur_type,prev_type,next_type;
- VECTOR cp1,cp2,cp3,cur_point,prev_point,next_point;
- DOUBLE cur_x,cur_y,prev_x,prev_y,next_x,next_y;
- DOUBLE tstep;
-
- if (font.NumContours(glyphnum)<1)
- return;
-
- if (contournum>=font.NumContours(glyphnum))
- return;
-
- if(polygon.numpoints>0)
- {
- delete polygon.pointlist;
- polygon.numpoints=0;
- }
-
- lastwasoff=0;
- consecutiveoffcount=0;
- offcount=0;
- for(i=0;i<font.NumPoints(glyphnum,contournum);i++)
- {
- // if (font.FontPointType(glyphnum,contournum,i)==ON_CURVE) cout<<i<<": ON"<<endl;
- // else cout<<i<<": OFF"<<endl;
- if(font.FontPointType(glyphnum,contournum,i)==OFF_CURVE)
- {
- offcount++;
- if(lastwasoff)
- consecutiveoffcount++;
- lastwasoff=1;
- }
- else
- lastwasoff=0;
- }
-
- polygon.numpoints = font.NumPoints(glyphnum,contournum) + offcount*(resolution-2) + consecutiveoffcount;
- polygon.pointlist = new VECTOR[polygon.numpoints+40]; // Temporary fix (give some playing room...)
-
- polyi=0;
-
- // pointcount = font.NumPoints(glyphnum,contournum);
- for(i=0;i<font.NumPoints(glyphnum,contournum);i++)
- {
-
- if (font.FontPointType(glyphnum,contournum,i)==ON_CURVE)
- {
- //cout<<"OnCURVE: "<<i<<endl;
- polygon.pointlist[polyi] = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(),
- (DOUBLE)font.FontPointY(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(), depth);
- polyi++;
- }
- else
- {
- //cout<<"OffCURVE: "<<i<<endl;
- if(font.FontPointType(glyphnum,contournum,i-1)==ON_CURVE)
- {
- cp1 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i-1)/(DOUBLE)font.UnitsPerEm(),
- (DOUBLE)font.FontPointY(glyphnum,contournum,i-1)/(DOUBLE)font.UnitsPerEm(), depth);
- }
- else
- {
- cp1 = VECTOR(((DOUBLE)font.FontPointX(glyphnum,contournum,i-1)+(DOUBLE)font.FontPointX(glyphnum,contournum,i))/2/(DOUBLE)font.UnitsPerEm(),
- ((DOUBLE)font.FontPointY(glyphnum,contournum,i-1)+(DOUBLE)font.FontPointY(glyphnum,contournum,i))/2/(DOUBLE)font.UnitsPerEm(), depth);
- }
-
- cp2 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(),
- (DOUBLE)font.FontPointY(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(), depth);
-
- if (i==(font.NumPoints(glyphnum,contournum)-1))
- {
- //cout<<"THE LAST ONE"<<endl;
- cp3 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,0)/(DOUBLE)font.UnitsPerEm(),
- (DOUBLE)font.FontPointY(glyphnum,contournum,0)/(DOUBLE)font.UnitsPerEm(), depth);
- }
- else
- {
- if(font.FontPointType(glyphnum,contournum,i+1)==ON_CURVE)
- {
- cp3 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i+1)/(DOUBLE)font.UnitsPerEm(),
- (DOUBLE)font.FontPointY(glyphnum,contournum,i+1)/(DOUBLE)font.UnitsPerEm(), depth);
- i++;
- }
- else
- {
- cp3 = VECTOR(((DOUBLE)font.FontPointX(glyphnum,contournum,i)+(DOUBLE)font.FontPointX(glyphnum,contournum,i+1))/2/(DOUBLE)font.UnitsPerEm(),
- ((DOUBLE)font.FontPointY(glyphnum,contournum,i)+(DOUBLE)font.FontPointY(glyphnum,contournum,i+1))/2/(DOUBLE)font.UnitsPerEm(), depth);
- }
- }
-
- tstep = 1.0/(DOUBLE)resolution;
- for(j=0;j<resolution;j++)
- {
- polygon.pointlist[polyi] = ApproximateQuadraticSpline(cp1,cp2,cp3,tstep*(j+1));
- polyi++;
- }
- }
- }
-
- if ( (polygon.pointlist[polyi-1].x==polygon.pointlist[0].x)
- && (polygon.pointlist[polyi-1].y==polygon.pointlist[0].y))
- {
- //cout<<"LAST IS FIRST"<<endl;
- polyi--; //temporary fix....
- }
-
- polygon.numpoints = polyi;
- polygon.orientation = polygon.findOrientation();
-
- //cout<<polygon<<"P";
- }
-
-
-
- //===========================================================================================================
- // TriangulateFace
- //-----------------------------------------------------------------------------------------------------------
- //===========================================================================================================
-
-
- void TriangulateFace (TTFont& font,
- USHORT glyphnum,
- USHORT resolution,
- DOUBLE shrinkFactor,
- LIST<TRIANGLE>& triangleList)
- {
-
-
- int i,j,k;
- BOOLEAN isAPair;
- SHORT contourCount;
- POLYGON* polyarray;
- POLYGON* shrunkpolyarray;
- BYTEPTR* relationship;
-
- // cout<<"Beginning to triangulate..."<<endl;
-
- contourCount = font.NumContours(glyphnum);
- if (contourCount<1) return;
-
- polyarray = new POLYGON[contourCount];
- if (polyarray==NULL)
- {
- cout<<"ERROR: Out of memory."<<endl;
- exit(1);
- }
-
- shrunkpolyarray=new POLYGON[contourCount];
- if (shrunkpolyarray==NULL)
- {
- cout<<"ERROR: Out of memory."<<endl;
- exit(1);
- }
-
- relationship = new BYTEPTR[contourCount];
- if (relationship==NULL)
- {
- cout<<"ERROR: Out of memory."<<endl;
- exit(1);
- }
- for (i=0;i<contourCount;i++)
- {
- relationship[i] = new BYTE[contourCount];
- if (relationship[i]==NULL)
- {
- cout<<"ERROR: Out of memory."<<endl;
- exit(1);
- }
- }
-
- for (i=0;i<contourCount;i++)
- {
- PolygonizeContour(font,glyphnum,i,resolution,0.0,polyarray[i]);
- if (shrinkFactor>0.0)
- polyarray[i].Shrink(shrunkpolyarray[i],shrinkFactor);
- }
-
-
-
-
- //cout<<"All Contours Polygonized."<<endl;
-
-
-
-
-
-
-
- for (i=0;i<contourCount;i++)
- for (j=0;j<contourCount;j++)
- if (i==j)
- relationship[i][j]=IGNORE;
- else if (polyarray[j].isInside(polyarray[i]))
- relationship[i][j]=INSIDE;
- else
- relationship[i][j]=OUTSIDE;
-
-
- for (i=0;i<contourCount;i++)
- {
- if (polyarray[i].orientation==CLOCKWISE)
- {
- for (j=0;j<contourCount;j++)
- {
- isAPair=FALSE;
- if (relationship[i][j]==INSIDE && polyarray[j].orientation==COUNTER_CLOCKWISE)
- {
- isAPair=TRUE;
- for (k=0;k<contourCount;k++)
- {
- if (k==j || k==i || relationship[k][j]==IGNORE) continue;
- if (relationship[k][j]==INSIDE)
- {
- if (relationship[i][k]==INSIDE)
- {
- isAPair=FALSE;
- exit;
- }
- }
- else
- continue;
- }
- }
- if (isAPair)
- {
- if (shrinkFactor>0.0)
- shrunkpolyarray[i].Combine(shrunkpolyarray[j]);
- else
- polyarray[i].Combine(polyarray[j]);
-
- relationship[i][j]=IGNORE;
- }
- }
- }
- }
-
-
- for (i=0;i<contourCount;i++)
- {
- if (polyarray[i].orientation==CLOCKWISE)
- {
- if (shrinkFactor>0.0)
- shrunkpolyarray[i].Triangulate(triangleList);
- else
- polyarray[i].Triangulate(triangleList);
- }
- }
-
-
- for (i=0;i<contourCount;i++)
- {
- delete polyarray[i].pointlist;
- delete shrunkpolyarray[i].pointlist;
- delete relationship[i];
- }
- delete polyarray;
- delete shrunkpolyarray;
- delete relationship;
-
- }
-
-
-
- //===========================================================================================================
- // TriangulateEdges
- //-----------------------------------------------------------------------------------------------------------
- //===========================================================================================================
-
-
- void TriangulateEdges(TTFont& font,
- USHORT glyphnum,
- USHORT resolution,
- DOUBLE frontDepth,
- DOUBLE backDepth,
- DOUBLE angleThreshold,
- LIST<TRIANGLE>& tlist)
- {
-
-
- INT i,j,k;
- TRIANGLE* t1;
- TRIANGLE* t2;
- VECTOR previous,current1,current2,next;
- VECTOR previousFacet,currentFacet,nextFacet;
- VECTOR previousFacetNormal,currentFacetNormal,nextFacetNormal;
- VECTOR averageNormal1,averageNormal2;
- VECTOR p1,p2,p3,p4;
- ULONG numberOfPoints;
- SHORT contourCount;
- POLYGON* polyarray;
- VECTOR zDir(0,0,1);
- DOUBLE angle1,angle2;
-
- contourCount = font.NumContours(glyphnum);
- if (contourCount<1) return;
-
- polyarray = new POLYGON[contourCount];
- if (polyarray==NULL)
- {
- cout<<"ERROR: Out of memory."<<endl;
- exit(1);
- }
-
- for (i=0;i<contourCount;i++)
- PolygonizeContour(font,glyphnum,i,resolution,0.0,polyarray[i]);
-
-
-
-
- for (i=0;i<contourCount;i++)
- {
- numberOfPoints = polyarray[i].numpoints;
-
- for (j=0;j<numberOfPoints;j++)
- {
-
- if (j==numberOfPoints-2)
- {
- previous = polyarray[i].pointlist[j-1];
- current1 = polyarray[i].pointlist[j];
- current2 = polyarray[i].pointlist[j+1];
- next = polyarray[i].pointlist[0];
- }
- else if (j==numberOfPoints-1)
- {
- previous = polyarray[i].pointlist[j-1];
- current1 = polyarray[i].pointlist[j];
- current2 = polyarray[i].pointlist[0];
- next = polyarray[i].pointlist[1];
- }
- else if (j==0)
- {
- previous = polyarray[i].pointlist[numberOfPoints-1];
- current1 = polyarray[i].pointlist[j];
- current2 = polyarray[i].pointlist[j+1];
- next = polyarray[i].pointlist[j+2];
- }
- else
- {
- previous = polyarray[i].pointlist[j-1];
- current1 = polyarray[i].pointlist[j];
- current2 = polyarray[i].pointlist[j+1];
- next = polyarray[i].pointlist[j+2];
- }
-
-
- previousFacet = ~(current1-previous);
- currentFacet = ~(current2-current1);
- nextFacet = ~(next-current2);
-
- previousFacetNormal = zDir^previousFacet;
- currentFacetNormal = zDir^currentFacet;
- nextFacetNormal = zDir^nextFacet;
-
- angle1 = acos(previousFacetNormal%currentFacetNormal);
- angle2 = acos(currentFacetNormal%nextFacetNormal);
-
- if (angle1<angleThreshold)
- averageNormal1 = ~(previousFacetNormal+currentFacetNormal);
- else
- averageNormal1 = currentFacetNormal;
-
- if (angle2<angleThreshold)
- averageNormal2 = ~(currentFacetNormal+nextFacetNormal);
- else
- averageNormal2 = currentFacetNormal;
-
- p1 = current1; p1.z=frontDepth;
- p2 = current1; p2.z=backDepth;
- p3 = current2; p3.z=frontDepth;
- p4 = current2; p4.z=backDepth;
-
- t1 = new TRIANGLE(p1,p2,p3,averageNormal1,averageNormal1,averageNormal2);
- if (t1==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
-
- t2 = new TRIANGLE(p2,p3,p4,averageNormal1,averageNormal2,averageNormal2);
- if (t2==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
-
- tlist.Add(t1);
- tlist.Add(t2);
- }
-
- }
-
- delete polyarray;
-
- }
-
-
-
-
-
- // This routine doesn't quite work yet. Sometimes if the polygon is 'shrunk' too much,
- // it can become self intersecting, which throws everything else off...
-
- void TriangulateBevels(TTFont& font, INT code, INT resolution,
- DOUBLE frontDepth, DOUBLE backDepth,
- DOUBLE faceShrink, DOUBLE edgeShrink,
- LIST<TRIANGLE>& tlist)
- {
- INT i,j;
- TRIANGLE* t1;
- TRIANGLE* t2;
- TRIANGLE* t3;
- TRIANGLE* t4;
- INT glyphnum;
- VECTOR p1,p2,p3,p4,p5,p6,p7,p8;
- SHORT contourCount;
- POLYGON* frontFacePolyArray;
- POLYGON* frontEdgePolyArray;
- POLYGON* backFacePolyArray;
- POLYGON* backEdgePolyArray;
-
- glyphnum = font.CharacterMap(code);
-
- contourCount = font.NumContours(glyphnum);
- if (contourCount<1) return;
-
- frontFacePolyArray = new POLYGON[contourCount];
- if (frontFacePolyArray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
- frontEdgePolyArray = new POLYGON[contourCount];
- if (frontEdgePolyArray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
- backFacePolyArray = new POLYGON[contourCount];
- if (backFacePolyArray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
- backEdgePolyArray = new POLYGON[contourCount];
- if (backEdgePolyArray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
-
- for (i=0;i<contourCount;i++)
- {
- PolygonizeContour(font,glyphnum,i,resolution,frontDepth,frontEdgePolyArray[i]);
- PolygonizeContour(font,glyphnum,i,resolution,backDepth,backEdgePolyArray[i]);
- frontEdgePolyArray[i].Shrink(frontFacePolyArray[i],faceShrink);
- backEdgePolyArray[i].Shrink(backFacePolyArray[i],faceShrink);
- frontEdgePolyArray[i].SetDepth(frontDepth-edgeShrink);
- backEdgePolyArray[i].SetDepth(backDepth+edgeShrink);
-
- for (j=0;j<frontEdgePolyArray[i].numpoints-1;j++)
- {
- p1 = frontFacePolyArray[i].pointlist[j];
- p2 = frontFacePolyArray[i].pointlist[j+1];
- p3 = frontEdgePolyArray[i].pointlist[j];
- p4 = frontEdgePolyArray[i].pointlist[j+1];
- p5 = backEdgePolyArray[i].pointlist[j];
- p6 = backEdgePolyArray[i].pointlist[j+1];
- p7 = backFacePolyArray[i].pointlist[j];
- p8 = backFacePolyArray[i].pointlist[j+1];
-
- cout<<"VECTORS: "<<p1<<p2<<p3<<p4<<p5<<p6<<p7<<p8<<endl;
-
- t1 = new TRIANGLE(p1,p3,p2);
- if (t1==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
- t2 = new TRIANGLE(p2,p3,p4);
- if (t2==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
- t3 = new TRIANGLE(p5,p7,p8);
- if (t3==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
- t4 = new TRIANGLE(p5,p8,p6);
- if (t4==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
-
- tlist.Add(t1);
- tlist.Add(t2);
- tlist.Add(t3);
- tlist.Add(t4);
- }
-
- p1 = frontFacePolyArray[i].pointlist[j];
- p2 = frontFacePolyArray[i].pointlist[0];
- p3 = frontEdgePolyArray[i].pointlist[j];
- p4 = frontEdgePolyArray[i].pointlist[0];
- p5 = backEdgePolyArray[i].pointlist[j];
- p6 = backEdgePolyArray[i].pointlist[0];
- p7 = backFacePolyArray[i].pointlist[j];
- p8 = backFacePolyArray[i].pointlist[0];
-
- t1 = new TRIANGLE(p1,p3,p2);
- if (t1==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
- t2 = new TRIANGLE(p2,p3,p4);
- if (t2==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
- t3 = new TRIANGLE(p5,p7,p8);
- if (t3==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
- t4 = new TRIANGLE(p5,p8,p6);
- if (t4==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
-
- tlist.Add(t1);
- tlist.Add(t2);
- tlist.Add(t3);
- tlist.Add(t4);
-
- }
-
- for (i=0;i<contourCount;i++)
- {
- delete frontFacePolyArray[i].pointlist;
- delete frontEdgePolyArray[i].pointlist;
- delete backEdgePolyArray[i].pointlist;
- delete backFacePolyArray[i].pointlist;
- }
- delete frontFacePolyArray;
- delete frontEdgePolyArray;
- delete backFacePolyArray;
- delete backEdgePolyArray;
-
- }
-
-
-